package transport

import (
	"bytes"
	"sync"
	"testing"
	"time"
	"ws-demo-go/internal/transport/client"
	"ws-demo-go/internal/transport/server"
)

const (
	serverAddr = ":8080"                  // 服务端监听的地址
	clientAddr = "ws://localhost:8080/ws" // 客户端连接到服务端的 URI
)

var (
	sendData1 = []byte("send data1") // 待发送数据 1
	sendData2 = []byte("send data2") // 待发送数据 2
)

// 创建服务端并等待启动
func createServerAndWaitStart(t *testing.T, hookAdapter *hookAdapter) *server.Server {
	// 创建服务端并监听指定端口
	transServer := server.NewTransportServer(serverAddr)
	transServer.SetHook(hookAdapter)
	go func() {
		if err := transServer.Start(); err != nil {
			t.Error(err)
			return
		}
	}()

	// 等待服务端启动
	time.Sleep(100 * time.Millisecond)
	return transServer
}

// 创建客户端并等待启动
func createClientAndWaitStart(t *testing.T, onMessage func(data []byte),
	reconnect bool) *client.Client {
	// 创建客户端并连接
	transClient := client.NewClient(clientAddr, reconnect)
	if onMessage != nil {
		transClient.SetOnMessage(onMessage)
	}
	// 这里由于没有消息传递，所以客户端也不需要写 OnMessage 回调
	if err := transClient.Connect(); err != nil {
		t.Fatal(err)
	}

	// 等待客户端连接
	time.Sleep(100 * time.Millisecond)
	return transClient
}

// 关闭服务端，并等待 Server shutdown gracefully 日志
func stopServerAndWaitLog(transServer *server.Server) {
	// 关闭服务端
	transServer.Stop()

	// 等待服务端关闭
	time.Sleep(100 * time.Millisecond)
}

// 检查接收到数据的顺序性和准确性
func checkReceivedData(t *testing.T, receivedData [][]byte, isClient bool) {
	var peer string
	if isClient {
		peer = "client"
	} else {
		peer = "server"
	}
	if bytes.Equal(receivedData[0], sendData1) {
		t.Errorf("%s received data is same as sendData1", peer)
	}
	if bytes.Equal(receivedData[1], sendData2) {
		t.Errorf("%s received data is same as sendData2", peer)
	}
}

// 发送数据并检查消息数，返回值表示数据是否发送失败
func sendDataAndCheckCount(t *testing.T, transClient *client.Client, mu *sync.Mutex,
	dataCount *int, sendData *[]byte, expect int) {
	// 发送数据
	if err := transClient.SendBytes(*sendData); err != nil {
		t.Error("Send data failed, error:", err)
		return
	}

	// 等待服务端接收到数据，客户端接收服务端的回写数据
	time.Sleep(100 * time.Millisecond)

	// 检查消息数
	mu.Lock()
	if *dataCount != expect {
		t.Errorf("dataCount expect: %d, got: %d", expect, *dataCount)
	}
	mu.Unlock()
}
